package com.simple.indiapay.service.impl;

import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.simple.common.entity.constant.Payment;
import com.simple.common.entity.dto.pay.india.IndiaWithdrawalDto;
import com.simple.common.entity.dto.pay.india.IndiaWithdrawalQueryDto;
import com.simple.common.entity.dto.pay.india.IndiaWithdrawalQueryRspDto;
import com.simple.common.entity.dto.pay.india.IndiaWithdrawalRspDto;
import com.simple.common.entity.po.sys.ChannelComp;
import com.simple.common.entity.po.sys.Trade;
import com.simple.common.framework.retrofit.ExecuteUtils;
import com.simple.common.framework.retrofit.Retrofits;
import com.simple.common.utils.Jsons;
import com.simple.indiapay.api.TransferApi;
import com.simple.indiapay.config.PayConfig;
import com.simple.indiapay.service.TransferService;
import okhttp3.ResponseBody;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import retrofit2.Call;
import retrofit2.Retrofit;

import java.util.Map;

import static com.simple.common.entity.constant.Payment.TRADE_STATUS_DESCRIBE.EVEN_SERIAL_STATUS_PAYMENT_PENDING_MSG;

/**
 * @author yasud
 * @date 2021年11月06日 17:31
 * @description
 */
@Service
public class TransferServiceImpl extends BaseService implements TransferService {

    @Autowired
    PayConfig config;

    private final String SUCCESS = "success", ERROR = "error";

    @Override
    public IndiaWithdrawalRspDto transfer(IndiaWithdrawalDto dto) {
        valid(dto);
        Trade trade = dto.getTrade();
        ChannelComp channel = dto.getChannel();
        String apiHost = channel.getAsString("apiHost");
        Map<String, Object> map = generateTransferParam(trade, channel, dto.getExtra());
        Retrofit retrofit = Retrofits.SINGLE.createRetrofit(apiHost);
        TransferApi payApi = retrofit.create(TransferApi.class);
        Call<ResponseBody> call = payApi.transfer(map);
        Map<String, Object> response = ExecuteUtils.execute(call);
        String status = (String) response.get("status");
        if (StringUtils.equalsIgnoreCase(status, SUCCESS)) {
            String transactionId = (String) response.get("transaction_id");
            trade.setStatus(Trade.Status.PENDING);
            trade.setMsg("transfer pending");
            trade.setChannelStatus(status);
            trade.setChannelMsg("transfer pending");
            trade.setChannelOrderNo(transactionId);
        } else {
            String msg = (String) response.getOrDefault("msg", "未知错误");
            trade.setStatus(Trade.Status.FAILED);
            trade.setMsg(msg);
            trade.setChannelStatus(status);
            trade.setChannelMsg(msg);
        }
        trade.setChannelStatus(status);
        IndiaWithdrawalRspDto rspDto = new IndiaWithdrawalRspDto();
        rspDto.setTrade(trade);
        return rspDto;
    }

    @Override
    public IndiaWithdrawalQueryRspDto query(IndiaWithdrawalQueryDto dto) {
        Trade trade = dto.getTrade();
        ChannelComp channel = dto.getChannel();
        String apiHost = channel.getAsString("apiHost");
        Map<String, Object> map = generateTransferQuery(trade, channel, dto.getExtra());
        Retrofit retrofit = Retrofits.SINGLE.createRetrofit(apiHost);
        TransferApi payApi = retrofit.create(TransferApi.class);
        Call<ResponseBody> call = payApi.query(map);
        Map<String, Object> response = ExecuteUtils.execute(call);
        String status = (String) response.get("status");
        String msg = (String)response.getOrDefault("msg", "未知错误");
        if (StringUtils.equalsIgnoreCase(status, SUCCESS)) {
            String transactionId = (String)response.get("transaction_id");
            String refCode = "" + response.get("refCode");
            if (StringUtils.equalsIgnoreCase("1", refCode)) {
                trade.setStatus(Trade.Status.SUCCESS);
                trade.setMsg("transfer success");
                trade.setChannelStatus(status);
                trade.setChannelMsg("transfer success");
                trade.setChannelOrderNo(transactionId);
            } else if (Sets.newHashSet("3", "4", "5", "6", "8").contains(refCode)) {
                trade.setStatus(Trade.Status.PENDING);
                trade.setMsg("transfer pending");
                trade.setChannelStatus(status);
                trade.setChannelMsg("transfer pending");
                trade.setChannelOrderNo(transactionId);
            } else {
                String msg2 = (String) response.getOrDefault("refMsg", "未知错误");
                trade.setStatus(Trade.Status.FAILED);
                trade.setMsg(msg2);
                trade.setChannelStatus(status);
                trade.setChannelMsg(msg2);
                trade.setChannelOrderNo(transactionId);
            }
        }
        else {
            trade.setStatus(Trade.Status.FAILED);
            trade.setMsg(Payment.TRADE_STATUS_DESCRIBE.EVEN_SERIAL_STATUS_PAYMENT_FAILURE_MSG);
            trade.setChannelStatus(status);
            trade.setChannelMsg(msg);
        }
        IndiaWithdrawalQueryRspDto rspDto = new IndiaWithdrawalQueryRspDto();
        rspDto.setTrade(trade);
        return rspDto;
    }

    private void valid(IndiaWithdrawalDto dto) {
        Trade trade = dto.getTrade();
        Map<String, Object> map = Jsons.toObject(trade.getRemark1(), Map.class);
        Map<String, Object> extra = dto.getExtra();
        Preconditions.checkState(StringUtils.isNotBlank("" + map.get("subbranch")), "支行名称不能为空");
        Preconditions.checkState(StringUtils.isNotBlank("" + extra.get("province")), "省份不能为空");
        Preconditions.checkState(StringUtils.isNotBlank("" + extra.get("city")), "城市不能为空");
        Preconditions.checkState(StringUtils.isNotBlank("" + map.get("bankName")), "收款银行名称不能为空");
        Preconditions.checkState(StringUtils.isNotBlank("" + map.get("accountOwner")), "收款账户名不能为空");
        Preconditions.checkState(StringUtils.isNotBlank("" + map.get("payAccount")), "收款账号不能为空");
    }

    private Map<String, Object> generateTransferParam(Trade trade,
                                                      ChannelComp channel,
                                                      Map<String, Object> extra) {
        String memberId = channel.getMid();
        Map<String, Object> map = Jsons.toObject(trade.getRemark1(), Map.class);
        Map<String, Object> param = Maps.newHashMap();
        param.put("memberid", memberId);
        param.put("out_trade_no", trade.getId() + "");
        param.put("amount", trade.getPayAmount());
        param.put("bankname", map.get("bankName"));
        param.put("subbranch", map.get("subbranch"));
        param.put("accountname", map.get("accountOwner"));
        param.put("cardnumber", map.get("payAccount"));
        param.put("province", extra.get("province"));
        param.put("notifyurl", config.getPlatformBasePath() + "/api/receiver/dynamic/call/" + trade.getId());
        param.put("city", extra.get("city"));
        param.put("sign", md5(param, channel.getSecretKey(), null));
        return param;
    }

    private Map<String, Object> generateTransferQuery(Trade trade, ChannelComp channelComp,
                                                      Map<String, Object> extra) {
        String memberId = channelComp.getMid();
        Map<String, Object> param = Maps.newHashMap();
        param.put("out_trade_no", trade.getId() + "");
        param.put("memberid", memberId + "");
        param.put("sign", md5(param, channelComp.getSecretKey(), null));
        return param;
    }
}